package com.example.hotel.common;

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Component
public class TokenIntercept implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查，如果不是映射到控制器方法的请求直接通过，一般是静态资源
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 检查要访问的控制器，如果不是自己包下的，如果不是直接跳过；例如：swagger文档的控制器
        if (!handler.toString().contains("com.example.hotel.controller")) {
            return true;
        }

        // 从请求头中获取 token
        String token = request.getHeader("Authorization");

        // 将处理器对象，类型转换为方法对象，需要获取方法上的注解信息
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 检查是否有passtoken注解，有则跳过检查token
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        // 如果没有passtoken注解，则进行Token验证
        if (JWTUtil.verify(token)) {
            return true;
        } else {
            // 验证不通过的，返回提示信息
            response.setContentType("application/json;utf-8");
            // 由于是response对象向前端写数据，这里就无法自动将对象转成json字符串了
            // 可以自己写一个工具类，将对象转json字符串，然后响应给前端。
            response.getWriter().write("{\"message\":\"用户令牌验证不通过\",\"code\":5001}");
            return false;
        }
        // 这里响应中带了中文，需要在配置文件中将下面的配置开启，否则会出中文乱码
        // server.servlet.encoding.force-response=true
    }
}
